//
//  AFHTTPSessionManager+In.m
//  Reactive AFNetworking Example
//
//  Created by Robert Widmann on 5/20/14.
//  Copyright (c) 2014 CodaFi. All rights reserved.
//

#import "AFHTTPSessionManager+In.h"

#import <ReactiveCocoa/ReactiveCocoa.h>

#import "HttpConstant.h"
#import "RetryTimeoutSessionDataTask.h"


@implementation AFHTTPSessionManager (In)

- (RACSignal *)rac_GET:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers {
    return [[self rac_requestPath:path parameters:parameters method:@"GET" headers:headers customParams:nil]
            setNameWithFormat:@"%@ -rac_GET: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_HEAD:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers {
    return [[self rac_requestPath:path parameters:parameters method:@"HEAD" headers:headers customParams:nil]
            setNameWithFormat:@"%@ -rac_HEAD: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_POST:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers {
    return [[self rac_requestPath:path parameters:parameters method:@"POST" headers:headers customParams:nil]
            setNameWithFormat:@"%@ -rac_POST: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_PUT:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers {
    return [[self rac_requestPath:path parameters:parameters method:@"PUT" headers:headers customParams:nil]
            setNameWithFormat:@"%@ -rac_PUT: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_PATCH:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers {
    return [[self rac_requestPath:path parameters:parameters method:@"PATCH" headers:headers customParams:nil]
            setNameWithFormat:@"%@ -rac_PATCH: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_DELETE:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers {
    return [[self rac_requestPath:path parameters:parameters method:@"DELETE" headers:headers customParams:nil]
            setNameWithFormat:@"%@ -rac_DELETE: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_requestPath:(NSString *)path parameters:(NSDictionary *)parameters method:(NSString *)method headers:(NSDictionary *)headers customParams:(NSDictionary *)customParams {
    AFHTTPRequestSerializer <AFURLRequestSerialization> *serializer = self.requestSerializer;
    if (customParams) {
        NSInteger timeout = [[customParams valueForKey:kHttpTimeout] integerValue];
        if (timeout > 0) {
            serializer.timeoutInterval = timeout;
        }
    }

    return [RACSignal createSignal:^(id <RACSubscriber> subscriber) {
        NSMutableURLRequest *request = [serializer requestWithMethod:method URLString:path parameters:parameters error:nil];
        [request setAllHTTPHeaderFields:headers];
        NSInteger httpRetries = kDefaultHttpRetries;
        NSInteger httpRetrytime = kDefaultHttpRetrytime;

        if (customParams) {
            NSInteger tmHttpRetries = [customParams[kHttpRetrytime] integerValue];
            NSInteger tmHttpRetrytime = [customParams[kHttpRetries] integerValue];
            if (tmHttpRetries > 0) {
                httpRetries = tmHttpRetries;
            }

            if (tmHttpRetrytime > 0) {
                httpRetrytime = tmHttpRetrytime;
            }
        }

        RetryTimeoutSessionDataTask *task = [[RetryTimeoutSessionDataTask alloc] initWithRequest:request numberOfRetries:httpRetries retryTime:httpRetrytime completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;

            NSDictionary *responseDict = (NSDictionary *) responseObject;
            NSNumber *success = responseObject[@"success"];

            if (success && ![success boolValue]) {
                NSString *message;
                if (responseDict[@"msg"]) {
                    message = responseDict[@"msg"];
                } else if (responseDict[@"message"]) {
                    message = responseDict[@"message"];
                } else {
                    message = @"";
                }

                NSError *myError = [NSError errorWithDomain:[ERROR_DOMAIM copy]
                                                       code:0
                                                   userInfo:@{ERROR_MESSAGE : message, ERROR_OBJECT : responseDict}];
                [subscriber sendError:myError];
            } else if (!httpResponse) {
                NSError *myError = [NSError errorWithDomain:[ERROR_DOMAIM copy]
                                                       code:1000
                                                   userInfo:@{ERROR_MESSAGE : @"网络请求超时!"}];
                [subscriber sendError:myError];
            } else if (httpResponse.statusCode >= 400 || error) {
                [subscriber sendError:error];
            } else if ([responseDict[@"status"] integerValue] == 403) {
                NSError *myError = [NSError errorWithDomain:[ERROR_DOMAIM copy]
                                                       code:403
                                                   userInfo:@{ERROR_MESSAGE : @"invalid token", ERROR_OBJECT : responseDict}];
                [subscriber sendError:myError];
            } else {
                [subscriber sendNext:responseObject];
                [subscriber sendCompleted];
            }
        }];

        task.taskCreator = ^NSURLSessionDataTask *(NSURLRequest *req, RACURLSessionRetryDataTaskBlock retryBlock) {
            return [self dataTaskWithRequest:req completionHandler:retryBlock];
        };

        [task resume];

        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }
    ];
}

@end

@implementation AFHTTPSessionManager (RequestCustom)

- (RACSignal *)rac_GET:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers customParams:(NSDictionary *)customParams {
    return [[self rac_requestPath:path parameters:parameters method:@"GET" headers:headers customParams:customParams]
            setNameWithFormat:@"%@ -rac_GET: %@, parameters: %@", self.class, path, parameters];
}

- (RACSignal *)rac_POST:(NSString *)path parameters:(NSDictionary *)parameters headers:(NSDictionary *)headers customParams:(NSDictionary *)customParams {
    return [[self rac_requestPath:path parameters:parameters method:@"POST" headers:headers customParams:customParams]
            setNameWithFormat:@"%@ -rac_POST: %@, parameters: %@", self.class, path, parameters];
}

@end